home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
4_0
/
LSC_MACW
/
MWR_READ.C
next >
Wrap
Text File
|
1988-12-03
|
10KB
|
333 lines
/*----------------------------------------------------------------------
MacWrite file to TEXT file converter.
Ignores pictures, does not treat tabs correctly.
But what the heck, it's a good start, and it's free.
Dan Kegel (d.r.kegel @ GEnie) November '88
------------------------------------------------------------------------*/
/* Get type definitions and prototypes for this module. */
#include "mwr.h"
/* Prototypes for private functions. */
static void Lose(char *);
static void *MyNewHandle(Size);
static void MySetHandleSize(Handle, Size);
/*--------------------------------------------------------------------
Report a fatal error to the user, then exit to the Finder (or whoever).
Calls FileError() in mini.file.c, which puts an alert on the screen
and waits for user to hit OK.
----------------------------------------------------------------------*/
static void
Lose(s)
char *s;
{
FileError(s, "\p");
ExitToShell();
}
/*---------------------------------------------------------------------
Routine to create a handle of given size; any errors are reported to
the user, then terminate the program.
Use when you don't expect any errors, but want to check just in case.
-----------------------------------------------------------------------*/
static void *
MyNewHandle(n)
Size n;
{
void *result;
result = (void *) NewHandle(n);
if (result == (void *)0)
Lose("\pOut of memory!");
return result;
}
/*---------------------------------------------------------------------
Routine to resize a handle to given size; any errors are reported to
the user, then terminate the program.
Use when you don't expect any errors, but want to check just in case.
-----------------------------------------------------------------------*/
static void
MySetHandleSize(h, n)
Handle h;
Size n;
{
SetHandleSize(h, n);
if (MemErr != 0)
Lose("\pOut of memory!");
}
/*----------------------------------------------------------------------
Read the given paragraph from the MacWrite file.
On entry, hPara is a handle to the buffer to store the data in;
it will be resized if it is too small.
Returns OSErr, which will be noErr if the operation succeded.
------------------------------------------------------------------------*/
OSErr
mwr_ReadParagraph(file, para_num, hPara)
mwr_opened_t *file;
int para_num;
Handle hPara;
{
long filePos;
long byteCount;
OSErr errno;
/* Determine where to read from the file, and seek there. */
filePos = file->hParaInfo[0][para_num].file_pos;
if (errno = SetFPos(file->refNum, fsFromStart, filePos))
return errno;
/* Determine how many bytes to read, allocate space, and read them. */
byteCount = file->hParaInfo[0][para_num].nbytes;
if (GetHandleSize(hPara) < byteCount) {
MySetHandleSize(hPara, byteCount);
}
if (errno = FSRead(file->refNum, &byteCount, *hPara))
return errno;
return noErr;
}
/*-----------------------------------------------------------------------
Copy a paragraph of MacWrite text into hTextBuf.
Decompresses only if compress_bit was set in this paragraph's info record.
hTextBuf is resized if it is not big enough to hold the paragraph.
CompressTab is a 15-byte array of the most common chars; in compressed
text, a nibble with a value of 0..14 is replaced by the corresponding
char from CompressTab; a nibble of 15 indicates that the following two
nibbles are a less-common character.
Returns number of chars in unpacked text.
------------------------------------------------------------------------*/
#define GETNIB(c, ip, nib) { \
c = *ip; \
if (nib == 1) { \
c &= 0x0f; \
ip++; \
} else \
c >>= 4; \
nib ^= 1; \
}
int
mwr_unpack(hPara_info_arr, para_num, hPara, hTextBuf,
compressTab)
mwr_para_info_t **hPara_info_arr;
int para_num; /* which paragraph */
Handle hPara;
Handle hTextBuf;
char *compressTab;
{
int nbytes;
/* Determine size of block when unpacked, resize output buffer
* if not big enough.
*/
nbytes = **((short **)hPara);
if (GetHandleSize(hTextBuf) < nbytes) {
MySetHandleSize(hTextBuf, nbytes);
}
if (hPara_info_arr[0][para_num].compress_bit == 0) {
/* Not compressed, just copy. */
BlockMove( *((char **)hPara) + 2,
*((char **)hTextBuf),
nbytes);
} else {
/* Compressed; decompress and copy. */
register char *op = *((char **)hTextBuf);
register unsigned char *ip = *((unsigned char **)hPara) + 2;
register int nibbleInChar = 0;
register int n = nbytes;
register unsigned char c;
while (n > 0) {
/* Get next nibble. */
GETNIB(c, ip, nibbleInChar)
if (c == 15) {
char d;
/* Not a frequent flier. Next two nibbles are char. */
GETNIB(d, ip, nibbleInChar)
GETNIB(c, ip, nibbleInChar)
c |= (d << 4);
} else {
/* Frequent flier. Grab char from compressTab. */
c = compressTab[c];
}
*op++ = c;
n--;
}
}
return nbytes;
}
/*---------------------------------------------------------------------
Open the given MacWrite file, read its header and paragraph info
array, places a structure describing it in *result.
Returns errno, which will be noErr if successful;
returns 1 if file is not in MacWrite 4.5 format.
WARNING: only works with Mac Plus and better ROM's, because
it calls OpenRFPerm().
-----------------------------------------------------------------------*/
OSErr
mwr_OpenFile(filename, vRef, result )
char *filename; /* file to read (pascal string) */
int vRef; /* file is on this volume */
mwr_opened_t *result; /* where to put result */
{
mwr_para_info_h hParaInfo; /* describes paragraphs in file */
Handle hPackTab; /* for MacWrite compression table */
int refNum;
OSErr errno;
long byteCount;
long filePos;
long temp;
int rsrcRefNum;
(void) pStrCopy(filename, result->name);
(void) PtoCstr(result->name);
/* Open file's resource fork, read file compression table.
* Use OpenRFPerm rather than OpenResFile so we can specify
* the directory the file is on! Won't work on old Fat Macs, tough.
*/
rsrcRefNum = OpenRFPerm(filename, vRef, fsRdPerm);
if ((rsrcRefNum == -1) ||
(hPackTab = GetResource(MWR_COMPRESS_RTYPE, MWR_COMPRESS_RID))==0) {
/* Some fool stripped the resource fork of the MacWrite file.
* Assume that the compression table is
* " etnroaisdlhcfp". Don't know how reliable this is!
*/
pStrCopy("\p etnroaisdlhcfp", result->compressTab);
} else {
/* Use the real compression table. */
pStrCopy(*hPackTab, result->compressTab);
/* Close resource file, discard loaded resources. */
CloseResFile(rsrcRefNum);
}
PtoCstr(result->compressTab);
/* Open file, read MacWrite header */
if ((errno = FSOpen(filename, vRef, &refNum)) != noErr)
return errno;
byteCount = sizeof(mwr_filehdr_t);
errno = FSRead(refNum, &byteCount, &result->header);
if (errno != noErr)
return errno;
/* Make sure it's the right format. */
if (result->header.macwrite_version != 6) {
/* Gack! Don't understand this format. Punt. */
FSClose(refNum);
return 1;
}
/* Read 'information array' for main document */
filePos = result->header.doc_win.info_pos;
byteCount = result->header.doc_win.info_len;
temp = result->header.doc_nparagraphs * sizeof(mwr_para_info_t);
if (byteCount != temp) {
/* File is inconsistant or not in MacWrite format */
FSClose(refNum);
return 1;
}
if (errno = SetFPos(refNum, fsFromStart, filePos))
return errno;
hParaInfo = MyNewHandle(byteCount);
errno = FSRead(refNum, &byteCount, *hParaInfo);
if (errno != noErr) {
DisposHandle(hParaInfo);
return errno;
}
/* Pack it all into an ugly structure */
result->refNum = refNum;
result->hParaInfo = hParaInfo;
return noErr;
}
/*--------------------------------------------------------------------
Close a MacWrite file after you have finished reading it.
----------------------------------------------------------------------*/
void
mwr_CloseFile( file )
mwr_opened_t *file;
{
OSErr errno;
errno = FSClose(file->refNum);
/* If we allowed writing to a file, we'd check the error code... */
DisposHandle(file->hParaInfo);
}
/*---------------------------------------------------------------------
Read the given MacWrite file, place it in the given TextEdit buffer.
This is kinda risky, because TextEdit buffers can only handle 32K of
data.
Returns noErr if successful, 1 if file was read but was too
big to entirely fit, or a file manager error code if there was one.
-----------------------------------------------------------------------*/
OSErr
mwr_TEReadFile(filename, vRef, hText )
void *filename; /* file to read (pascal string) */
int vRef; /* file is on this volume or directory */
TEHandle hText; /* where to put text */
{
Handle hPara; /* for incoming paragraphs of text */
Handle hTextBuf; /* ditto, after decompression */
mwr_opened_t file; /* describes open file */
int para, nPara;
int count;
OSErr errno;
errno = mwr_OpenFile((char *)filename, vRef, &file);
if (errno != noErr)
return errno;
/* Allocate paragraph buffer, clear TextEdit buffer */
hPara = MyNewHandle(2048); /* start off with 2K buffer */
hTextBuf = MyNewHandle(2048);
TESetSelect(0, (**hText).teLength, hText);
TEDelete( hText );
/* For each paragraph in file */
nPara = file.header.doc_nparagraphs;
for (para=0; para < nPara; para++) {
if (file.hParaInfo[0][para].height > 0) {
/* Read paragraph in MacWrite format */
errno = mwr_ReadParagraph(&file, para, hPara);
if (errno != noErr) break;
/* Convert to TEXT format */
count = mwr_unpack(file.hParaInfo, para,
hPara, hTextBuf, file.compressTab);
/* Insert into TextEdit record */
if ((long) count + (long) hText[0]->teLength < 32760)
TEInsert( *hTextBuf, count, hText );
else {
/* Too much text! */
errno = 1;
break;
}
}
}
/* Deallocate buffers, close input file */
DisposHandle(hTextBuf);
DisposHandle(hPara);
mwr_CloseFile(&file);
return errno;
}